package cn.anc.aonicardv.net;

import android.net.Network;
import android.text.TextUtils;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import retrofit2.Converter;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * Created by yangdai on 2017/6/7.
 */

public class NetRequestClient {

    private Retrofit retrofit;

    public static class Builder {

        private static final int DEFAULT_MAXIDLE_CONNECTIONS = 5;
        private static final long DEFAULT_KEEP_ALIVEDURATION = 8;
        private Retrofit.Builder builder;
        private OkHttpClient.Builder okHttpBuilder;

        public Builder() {
            if (builder == null) {
                ConnectionPool connectionPool = new ConnectionPool(DEFAULT_MAXIDLE_CONNECTIONS, DEFAULT_KEEP_ALIVEDURATION, TimeUnit.SECONDS);
                okHttpBuilder = new OkHttpClient.Builder();
                okHttpBuilder.connectionPool(connectionPool).connectTimeout(5, TimeUnit.SECONDS);
                X509TrustManager x509TrustManager = getX509TrustManager();
                okHttpBuilder.sslSocketFactory(getSSLSocketFactory(x509TrustManager), x509TrustManager);
                okHttpBuilder.hostnameVerifier(getHostNameVerifier());
                this.builder = new Retrofit.Builder().client(okHttpBuilder.build()).addCallAdapterFactory(RxJavaCallAdapterFactory.create());
            }
        }
        public Builder baseUrl(String url) {
            if (!TextUtils.isEmpty(url)) {
                builder.baseUrl(url);
            }
            return this;
        }

        public Builder addConverterFactory(Converter.Factory factory) {
            if (factory != null)
                builder.addConverterFactory(factory);
            return this;
        }

        public Builder setNetwork(Network network) {
            if (network != null) {
                okHttpBuilder.socketFactory(new NetworkSocketFactory(network));
                builder.client(okHttpBuilder.build());
            }
            return this;
        }

        public NetRequestClient build() {
            return new NetRequestClient(builder);
        }

        public X509TrustManager getX509TrustManager() {
            return new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) {
                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    X509Certificate[] x509Certificates = new X509Certificate[0];
                    return x509Certificates;
                }
            };
        }

        private SSLSocketFactory getSSLSocketFactory(X509TrustManager x509TrustManager) {
            SSLContext sslContext = null;
            try {
                sslContext = SSLContext.getInstance("SSL");
                sslContext.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom());
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (KeyManagementException e) {
                e.printStackTrace();
            }
            return sslContext.getSocketFactory();
        }

        public HostnameVerifier getHostNameVerifier() {
            return new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            };
        }
    }

    private NetRequestClient(Retrofit.Builder builder) {
        retrofit = builder.build();
    }

    public Retrofit getRetrofit() {

        return retrofit;
    }

    public Subscription execute(Observable observable, Subscriber subscribers) {
        return observable.subscribeOn(Schedulers.io()).unsubscribeOn(AndroidSchedulers.mainThread()).observeOn(Schedulers.io()).subscribe(subscribers);
    }

    public Subscription execute2(Observable observable, Subscriber subscribers) {
        return observable.subscribeOn(Schedulers.io()).unsubscribeOn(AndroidSchedulers.mainThread()).observeOn(AndroidSchedulers.mainThread()).subscribe(subscribers);
    }
}
